#region using statements

using System;

using Microsoft.Xna.Framework;

#endregion

namespace NGen.Systems.StringAlarms
{
	/// <summary>
	/// 	This is the actual alarm object. Once the timer expires, it will send the message back to its parent
	/// </summary>
	public class AlarmObject
	{
		#region delegates

		/// <summary>
		/// 	Delegate for alarm event throwing
		/// </summary>
		/// <param name = "p_alarmMessage">the string message sent from the alarm</param>
		public delegate void AlarmEventHandler(string p_alarmMessage);

		#endregion

		#region events

		/// <summary>
		/// 	Event object that stores the reference to the callback function of the parent
		/// </summary>
		private event AlarmEventHandler m_eventAlarm;

		#endregion

		#region local fields

		/// <summary>
		/// 	the message sent by the alarm back to the parent object
		/// </summary>
		private readonly string m_message;

		/// <summary>
		/// 	represents the time left until this alarm activates
		/// </summary>
		private double m_timer;

		#endregion

		#region properties

		/// <summary>
		/// 	Gets the time remaining until this alarm is triggered
		/// </summary>
		public double TimeRemaning {
			get { return m_timer; }
			set { m_timer = value; }
		}

		/// <summary>
		/// 	Returns the message stored in the alarm
		/// </summary>
		public string GetMessage {
			get { return m_message; }
		}

		/// <summary>
		///		add or remove a listener from receiving events from this alarm
		/// </summary>
		public event AlarmEventHandler AlarmEvent {
			add { m_eventAlarm += value; }
			remove { m_eventAlarm -= value; }
		}

		#endregion

		#region constructors

		/// <summary>
		/// 	Constructor sets the timer, message. You must manually register for the alarm event
		/// </summary>
		/// <param name = "p_alarmTime">the duration of the alarm</param>
		/// <param name = "p_alarmMessage">the message to pass to the callback method</param>
		public AlarmObject(double p_alarmTime, string p_alarmMessage) {
			m_timer = p_alarmTime;
			m_message = p_alarmMessage;
		}

		/// <summary>
		/// 	Constructor sets the timer, message and parent
		/// </summary>
		/// <param name = "p_parent">the object that will receive the alarm callback</param>
		/// <param name = "p_alarmTime">the duration of the alarm</param>
		/// <param name = "p_alarmMessage">the message to pass to the callback method</param>
		public AlarmObject(object p_parent, double p_alarmTime, string p_alarmMessage) {
			if(!(p_parent is IAlarmListener)) {
				throw new SystemException("object listener passed in does not implement IAlarmSystemCallbacks");
			}

			AlarmEvent += (p_parent as IAlarmListener).OnAlarmEvent;
			m_timer = p_alarmTime;
			m_message = p_alarmMessage;
		}

		#endregion

		#region local methods

		/// <summary>
		/// 	<para>Update the alarm time. If the timer reaches 0 then throw the callback event
		/// 		and return true so that the alarm system will remove the alarm</para>
		/// 	<para>If you override this method, be sure to return true whenever you wish for the
		/// 		alarm to be removed from the alarm system. Otherwise the alarm will always exist.</para>
		/// </summary>
		/// <param name = "p_gameTime">the game time object</param>
		/// <returns>true if the alarm should be removed from the alarm system, false otherwise</returns>
		public virtual bool Update(GameTime p_gameTime) {
			m_timer -= p_gameTime.ElapsedGameTime.TotalSeconds;
			if(m_timer <= 0) {
				Action();
				return true;
			}
			return false;
		}

		/// <summary>
		/// 	<para>The action to take once the alarm timer reaches 0</para>
		/// </summary>
		public virtual void Action() {
			if(m_eventAlarm != null)
				m_eventAlarm(m_message);
		}

		#endregion
	}
}